import { useState, useEffect } from "react";
import "./StoForm.scss"

type FormItemType = "text" | "password" | "select" | "form" | "rich-text";
type imgSize = [number, number]

interface IFormCell {
    label: string,
    required: boolean,
    type: string | undefined,
    rowSpan: number,
    colSpan: number,
    values: string[],
    valueGetter: Function,
    defaultLines: number,
    formFrame: FormCell[][],
    defaultRows: number,
    text: string,
    src: string,
    size: number[],
    key: string,
    readonly: boolean,
}

type FormCell = Partial<IFormCell>

type StoFormProps = {
    formFrame: FormCell[][],
    formData?: Record<string, any>
    width?: number,
    inset?: boolean,
    editable?: boolean,
    formTitle?: string,
    onConfirm?: (newData: any) => void
}

/* 所有的DOM事件都要加防抖 */
let debounce: null | ((fn: Function, delay?: number) => Function) = (fn: Function, delay = 1000) => {
    let timer: NodeJS.Timeout | null = null;

    return function (...args: any[]) {

        if (timer) {
            clearTimeout(timer)
            timer = null
        }

        timer = setTimeout(() => {
            fn.apply(null, args)
            timer = null
        }, delay);

    }
}

const StoForm: React.FC<StoFormProps> = ({ formFrame: frame, formData: _data, width, inset = false, editable = false, formTitle, onConfirm }) => {

    const updateFormData = (key: string, value: any) => {
        setFormData({
            ...formData,
            [key]: value
        })
    }

    const debouncedOnChange = debounce!(
        (e: any, key: string) => {
            console.log("debouncedOnChange", e.target.value);
            setFormData({
                ...formData,
                [key]: e.target.value
            })
        }
    )

    const renderCell = (cell: FormCell, data: Record<string, any>) => {
        const { key, required, label, type, values, formFrame, defaultRows, text, size, readonly } = cell

        const starfix = <span style={{ color: 'red', paddingRight: '0.25rem', visibility: required ? 'visible' : 'hidden' }}>*</span>

        let inputer;
        switch (type) {

            case "select":
                inputer = (
                    <>
                        <label>
                            {starfix}
                            {label}
                        </label>
                        <select
                            onChange={e => debouncedOnChange(e, key)} disabled={!editable || readonly} defaultValue={data[key!]}>
                            {
                                values
                                    ? values?.map(
                                        v => <option key={v} value={v}>{v}</option>
                                    )
                                    : <option value={data[key!]}>{data[key!]}</option>
                            }
                        </select>
                    </>
                )
                break;

            case "richtext":
                inputer = <textarea disabled={!editable} rows={defaultRows} defaultValue={data[key!]}
                    onChange={e => debouncedOnChange(e, key)}></textarea>
                break;

            case "btn":
                inputer = <button disabled={!editable} style={{ width: "100%" }}>{text}</button>
                break;

            case "img":
                inputer = <img src={data[key!]} style={{ width: size![0] }} alt="" />
                break;

            case "form":
                inputer = <StoForm editable={editable} inset={true} formFrame={formFrame!} formData={data}></StoForm>
                break;

            default:
                inputer = (
                    <>
                        <label htmlFor="">{starfix}{label}</label>
                        <input disabled={!editable} type={type} placeholder={`请输入${label}`} defaultValue={data[key!]}
                            onChange={e => debouncedOnChange(e, key)}
                        />
                    </>
                )
                break;
        }

        return inputer
    }

    const [formData, setFormData] = useState(_data)

    // /* 释放防抖闭包 */
    // useEffect(() => {
    //     return () => {
    //         console.log("ComponentWillUnmount");
    //         debounce = null
    //         console.log("防抖闭包已释放！");
    //     }
    // }, [])

    return (
        <table width={width + "px"} className={inset ? "inset" : ""}>
            {/* <caption>Example Table</caption> */}

            {
                formTitle && (
                    <thead>
                        <tr>
                            <th style={{ padding: '.5rem' }} colSpan={100}>{formTitle}</th>
                        </tr>
                    </thead>
                )
            }

            <tbody>

                {
                    frame.map(
                        (rowCells, rowIndex) => (
                            <tr key={rowIndex}>
                                {
                                    rowCells.map(
                                        (cell, colIndex) =>
                                            <td key={colIndex} rowSpan={cell.rowSpan || 1} colSpan={cell.colSpan || 1}>
                                                {renderCell(cell, formData!)}
                                            </td>
                                    )
                                }
                            </tr>
                        )
                    )
                }

                {
                    !inset && (
                        <tr>
                            <td colSpan={100} style={{ textAlign: 'right' }}>
                                {editable && <button onClick={() => onConfirm!(formData)} className="wide">确定</button>}
                                <button style={{ marginLeft: '1rem' }} className="wide" onClick={() => window.history.back()}>返回</button>
                            </td>
                        </tr>
                    )
                }

            </tbody>

        </table>
    );

};

export default StoForm;